package state.socket;

import particle.core.network.Socket;
import particle.core.tools.ByteBuffer;
import state.GameControl;
import state.GameGlobal;

public class ClientConnection extends GameControl implements DataReceiveListener {
  private Socket sc = null;
  private ByteBuffer inputStream = null;
  private ByteBuffer outputStream = null;

  private WriterThread writerThread = null;
  private ReaderThread readerThread = null;
  private DataReceiveListener listener = null;

  private String serverUrl = null;
  private int port = 0;
  public boolean isConnectSuccess = false;

  public boolean isRunning = true;
  private int heartBreathSequenceTime = 0;
  private DataPackage heartBreathDataPackage = null;

  public ClientConnection(String serverUrl1, int port1, DataReceiveListener listener1, int heartBreathSequenceTime1) {
    this.heartBreathSequenceTime = heartBreathSequenceTime1;
    setTimeInterval(heartBreathSequenceTime1);
    setRepeat(true);
    this.serverUrl = serverUrl1;
    this.port = port1;
    this.listener = listener1;
    heartBreathDataPackage = DataPackage.createDataPackage1(DefaultProtocolConstants.RequestHeader.HEART_BREATH_REQUEST);

    new GameControl() {
      public void perform() {
        connect();
      }
    }.setTimeInterval(10).start();

    // Start to check to send heart breath package
    start();
  }

  public void perform() {
    if (!isConnectSuccess) {
      return;
    }
    writerThread.write(heartBreathDataPackage);
  }

  private void connect() {
    inputStream = new ByteBuffer();
    outputStream = new ByteBuffer();
    sc = Socket.newSocket();
    if (sc == null) {
      // Socket creation failed. Either the device is out of resources, or the app is misconfigured.
      System.out.println("Socket creation failed.");
      return;
    }
    writerThread = new WriterThread(outputStream, this);
    readerThread = new ReaderThread(inputStream, this, this);
    sc.setConnectionTimeout(GameGlobal.TIME_OUT);
    sc.addConnectEventHandler(readerThread);
    sc.addDataReceiveEventHandler(readerThread);
    sc.addStatusEventHandler(readerThread);
    sc.connect(serverUrl, port, inputStream);
  }

  public Socket getSocket() {
    return sc;
  }

  public void onRecieveData(DataPackage dataPackage) {
    if (listener != null) {
      listener.onRecieveData(dataPackage);
    }
  }

  public void onConnectDone() {
    if (listener != null) {
      listener.onConnectDone();
    }
  }

  public void onConnectFail() {
    if (listener != null) {
      listener.onConnectFail();
    }
  }

  public void onDisconnect() {
    if (listener != null) {
      listener.onDisconnect();
    }
  }

  public void setListener(DataReceiveListener listener1) {
    this.listener = listener1;
  }

  public void write(DataPackage dataPackage) {
    if (writerThread != null) {
      writerThread.write(dataPackage);
    } else {
      System.out.println(">>>>>>ERROR: writerThread is NULL");
      detroy();
    }
  }

  public int getHeartBreathSequenceTime() {
    return heartBreathSequenceTime;
  }

  public void setHeartBreathSequenceTime(int heartBreathSequenceTime1) {
    this.heartBreathSequenceTime = heartBreathSequenceTime1;
    sc.setConnectionTimeout(GameGlobal.TIME_OUT);
    setTimeInterval(heartBreathSequenceTime1);
  }

  public void detroy() {
    stop();
    isRunning = false;
    isConnectSuccess = false;
    if (readerThread != null) {
      readerThread.detroy();
      readerThread = null;
    }

    if (writerThread != null) {
      writerThread.detroy();
      writerThread = null;
    }

    if (inputStream != null) {
      inputStream.clear();
      inputStream = null;
    }

    if (outputStream != null) {
      outputStream.clear();
      outputStream = null;
    }

    if (sc != null) {
      sc.disconnect(true);
      sc = null;
    }

    listener = null;
    serverUrl = null;
  }
}
